home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
libs
/
intuisup.lha
/
Intuisup
/
source.lha
/
Render
/
render.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-14
|
29KB
|
958 lines
/* $Revision Header *** Header built automatically - do not edit! ***********
*
* (C) Copyright 1991 by Torsten Jürgeleit
*
* Name .....: render.c
* Created ..: Thursday 19-Dec-91 15:14:35
* Revision .: 12
*
* Date Author Comment
* ========= ==================== ====================
* 14-Sep-92 Torsten Jürgeleit open_window(): new flag to prevent
* adding of inner window offsets
* 28-Jul-92 Torsten Jürgeleit save window pointer in RenderInfo
* 28-Jul-92 Torsten Jürgeleit open_window(): now correct window
* position if RENDER_INFO_FLAG_-
* INNER_WINDOW set
* 23-Jun-92 Torsten Jürgeleit close_window() now checks if
* win->UserPort exists before trying
* to reply all IntuiMessages
* 22-Jun-92 Torsten Jürgeleit after modifying NewWindow struct
* for inner window mode new window
* dimension is scaled once again in
* open_window()
* 12-May-92 Torsten Jürgeleit text colors for clear_window()
* 30-Apr-92 Torsten Jürgeleit raster for clear_window()
* 26-Apr-92 Torsten Jürgeleit special algorithm to calc text 2
* pen for screens with 1 or 2 planes
* 22-Mar-92 Torsten Jürgeleit mungwall hit in create_avail_fonts
* no CopyMem() instead of 2nd
* AvailFonts() allowed
* 18-Mar-92 Torsten Jürgeleit calc inner window dimension BEFORE
* centering window in open_window()
* 06-Jan-92 Torsten Jürgeleit add font support routines
* 19-Dec-91 Torsten Jürgeleit Created this file!
*
****************************************************************************
*
* Routines to get information needed to render ISUP objects and some
* window support functions
*
* $Revision Header ********************************************************/
/* Includes */
#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/diskfont.h>
#include <intuition/intuition.h>
#ifdef AZTEC_C
#include <functions.h> /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
#endif
#include <libraries/memwatch.h> /* header file for memory debug link library (Fish 240) - AFTER functions.h */
#include "render.h"
/* Defines */
#define RED_SCALE 3 /* amount of RGB values to take in account the different visual impact of those colors */
#define GREEN_SCALE 6
#define BLUE_SCALE 2
#define DEFAULT_AVAIL_FONTS_BUFFER_SIZE 1000
/* Externals */
IMPORT struct IntuitionBase *IntuitionBase;
/* Statics */
STATIC USHORT image_data_arrow_left[] = { /* bitmap data for left arrow image */
0x0780, 0x3e00, 0xf800, 0x3e00, 0x0780, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000
};
STATIC USHORT image_data_arrow_right[] = { /* bitmap data for right arrow image */
0xf000, 0x3e00, 0x0f80, 0x3e00, 0xf000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000
};
STATIC USHORT image_data_arrow_up[] = { /* bitmap data for up arrow image */
0x0800, 0x1c00, 0x3e00, 0x7700, 0xc180, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000
};
STATIC USHORT image_data_arrow_down[] = { /* bitmap data for down arrow image */
0xc180, 0x7700, 0x3e00, 0x1c00, 0x0800, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000
};
STATIC USHORT image_data_toggle_knob_unselected[] = { /* bitmap data for unselected toggle knob image */
0x1ffc, 0x0000, 0x7000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000,
0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x7000, 0x0000,
0x1000, 0x0000, /* Plane 0 */
0x0002, 0x0000, 0x0003, 0x8000, 0x0000, 0xc000, 0x0000, 0xc000,
0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0003, 0x8000,
0x0ffe, 0x0000 /* Plane 1 */
};
STATIC USHORT image_data_toggle_knob_selected[] = { /* bitmap data for selected toggle knob image */
0x0002, 0x0000, 0x0003, 0x8000, 0x03f0, 0xc000, 0x0ffc, 0xc000,
0x0ffc, 0xc000, 0x0ffc, 0xc000, 0x03f0, 0xc000, 0x0003, 0x8000,
0x0ffe, 0x0000, /* Plane 0 */
0x1ffc, 0x0000, 0x7000, 0x0000, 0xc3f0, 0x0000, 0xcffc, 0x0000,
0xcffc, 0x0000, 0xcffc, 0x0000, 0xc3f0, 0x0000, 0x7000, 0x0000,
0x1000, 0x0000 /* Plane 1 */
};
STATIC USHORT image_data_toggle_check_selected[] = { /* bitmap data for selected toggle checkmark image */
0x0038, 0x0060, 0x00c0, 0xe180, 0x7300, 0x3e00, 0x1c00
};
STATIC USHORT image_data_cycle[] = { /* bitmap data for cycle image */
0x7f01, 0xc181, 0xc181, 0xc7e1, 0xc3c1, 0xc181, 0xc001, 0xc181,
0x7f01, /* Plane 0 */
0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
0x0002 /* Plane 1 */
};
STATIC USHORT image_data_count_left[] = { /* bitmap data for left count image */
0x0700, 0x3f00, 0xff00, 0x3f00, 0x0700
};
STATIC USHORT image_data_count_right[] = { /* bitmap data for right count image */
0xe000, 0xfc00, 0xff00, 0xfc00, 0xe000
};
STATIC struct Image images[] = {
{ /* left arrow */
0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
&image_data_arrow_left[0], 0, 0, NULL
}, { /* right arrow */
0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
&image_data_arrow_right[0], 0, 0, NULL
}, { /* up arrow */
0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
&image_data_arrow_up[0], 0, 0, NULL
}, { /* down arrow */
0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
&image_data_arrow_down[0], 0, 0, NULL
}, { /* toggle select knob unselected */
0, 0, IMAGE_KNOB_WIDTH, IMAGE_KNOB_HEIGHT, IMAGE_KNOB_DEPTH,
&image_data_toggle_knob_unselected[0], 0, 0, NULL
}, { /* toggle select knob selected */
0, 0, IMAGE_KNOB_WIDTH, IMAGE_KNOB_HEIGHT, IMAGE_KNOB_DEPTH,
&image_data_toggle_knob_selected[0], 0, 0, NULL
}, { /* toggle select check unselected */
IMAGE_HORIZ_OFFSET, IMAGE_VERT_OFFSET, IMAGE_CHECK_WIDTH,
IMAGE_CHECK_HEIGHT, 0, NULL, 0, 0, NULL
}, { /* toggle select check selected */
IMAGE_HORIZ_OFFSET, IMAGE_VERT_OFFSET, IMAGE_CHECK_WIDTH,
IMAGE_CHECK_HEIGHT, IMAGE_CHECK_DEPTH,
&image_data_toggle_check_selected[0], 0, 0, NULL
}, { /* cycle */
0, 0, IMAGE_CYCLE_WIDTH, IMAGE_CYCLE_HEIGHT, IMAGE_CYCLE_DEPTH,
&image_data_cycle[0], 0, 0, NULL
}, { /* left count */
0, 0, IMAGE_COUNT_WIDTH, IMAGE_COUNT_HEIGHT, IMAGE_COUNT_DEPTH,
&image_data_count_left[0], 0, 0, NULL
}, { /* right count */
0, 0, IMAGE_COUNT_WIDTH, IMAGE_COUNT_HEIGHT, IMAGE_COUNT_DEPTH,
&image_data_count_right[0], 0, 0, NULL
}
};
STATIC struct TextAttr topaz80_attr = { (STRPTR)"topaz.font", TOPAZ_EIGHTY,
FS_NORMAL, FPF_ROMFONT };
/* Static prototypes */
SHORT calc_color_level(SHORT color);
VOID init_render_info_images(struct RenderInfo *ri);
UBYTE get_image_pixel_color(struct Image *image, USHORT x, USHORT y);
VOID set_image_pixel_color(struct Image *image, USHORT x, USHORT y,
UBYTE color);
BOOL create_avail_fonts(struct RenderInfo *ri);
VOID free_avail_fonts(struct RenderInfo *ri);
/* Static pragmas */
#pragma regcall(calc_color_level(d0))
#pragma regcall(init_render_info_images(a0))
#pragma regcall(get_image_pixel_color(a0,d0,d1))
#pragma regcall(set_image_pixel_color(a0,d0,d1,d2))
#pragma regcall(create_avail_fonts(a0))
#pragma regcall(free_avail_fonts(a0))
/* Get render info for given screen */
struct RenderInfo *
get_render_info(struct Screen *screen, USHORT flags)
{
struct RenderInfo *ri;
if (ri = AllocMem((LONG)sizeof(struct RenderInfo),
(LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
struct Screen screen_data;
USHORT screen_type;
/* Get screen data - if no screen given then use workbench screen */
if (!screen) {
LONG ilock;
/* Get pointer to workbench screen */
ilock = LockIBase(0L);
screen = IntuitionBase->FirstScreen;
while (screen && (screen->Flags & SCREENTYPE) != WBENCHSCREEN) {
screen = screen->NextScreen;
}
UnlockIBase(ilock);
screen_type = WBENCHSCREEN;
} else {
screen_type = CUSTOMSCREEN;
}
if (GetScreenData((BYTE *)&screen_data, (LONG)sizeof(struct Screen),
(LONG)screen_type, screen) == TRUE) {
struct Image *image;
USHORT *data;
ULONG data_size;
SHORT i;
/* Get screen and window data */
ri->ri_Screen = screen;
screen = &screen_data;
ri->ri_ScreenWidth = screen->Width;
ri->ri_ScreenHeight = screen->Height;
ri->ri_ScreenDepth = screen->RastPort.BitMap->Depth;
ri->ri_WindowBorderTop = screen->BarHeight -
screen->BarVBorder + screen->WBorTop;
ri->ri_WindowBorderLeft = screen->WBorLeft;
ri->ri_WindowBorderRight = screen->WBorRight;
ri->ri_WindowBorderBottom = screen->WBorBottom;
ri->ri_Flags = flags;
ri->ri_ID = ISUP_ID;
/* Calc chipmem buffer size for image data */
for (i = 0, image = &images[0], data_size = 0;
i < MAX_RENDER_IMAGES; i++, image++) {
if (image->ImageData) {
data_size += (image->Width / 16 + (image->Width & 15 ? 1 : 0))
* image->Height * ri->ri_ScreenDepth * 2;
}
}
if (data = AllocMem(data_size,
(LONG)MEMF_PUBLIC | MEMF_CHIP | MEMF_CLEAR)) {
SHORT num_colors;
/* Insert image data buffer and size */
ri->ri_ImageData = data;
ri->ri_ImageDataSize = data_size;
/* Calculate render colors */
if ((num_colors = 1 << ri->ri_ScreenDepth) > MAX_RENDER_COLORS) {
num_colors = MAX_RENDER_COLORS;
}
if (num_colors < 3) {
/* Set render pens for monochrome screen */
if (flags & RENDER_INFO_FLAG_BACK_FILL) {
ri->ri_HighlightPen = 0;
ri->ri_ShadowPen = 0;
ri->ri_TextPen1 = 0;
ri->ri_TextPen2 = 0;
ri->ri_BackPen = 1;
} else {
ri->ri_HighlightPen = 1;
ri->ri_ShadowPen = 1;
ri->ri_TextPen1 = 1;
ri->ri_TextPen2 = 1;
ri->ri_BackPen = 0;
}
} else {
struct ColorMap *cmap;
SHORT back_color, max_diff, colors[MAX_RENDER_COLORS],
color_levels[MAX_RENDER_COLORS],
pens[MAX_RENDER_COLORS];
/* Get current screen colors */
Forbid();
for (i = 0, cmap = screen->ViewPort.ColorMap; i < num_colors;
i++) {
colors[i] = GetRGB4(cmap, (LONG)i);
color_levels[i] = calc_color_level(colors[i]);
pens[i] = i;
}
Permit();
/* Save normal background color */
back_color = colors[0];
/* Sort colors darkest to brightest (BUBBLE SORT) */
for (i = 0; i < (num_colors - 1); i++) {
SHORT j;
for (j = i + 1; j < num_colors; j++) {
if (color_levels[i] > color_levels[j]) {
SHORT temp;
/* Swap colors, color levels and pens */
temp = colors[i];
colors[i] = colors[j];
colors[j] = temp;
temp = color_levels[i];
color_levels[i] = color_levels[j];
color_levels[j] = temp;
temp = pens[i];
pens[i] = pens[j];
pens[j] = temp;
}
}
}
if (flags & RENDER_INFO_FLAG_BACK_FILL) {
/* Set render pens - highlight pen first */
ri->ri_HighlightPen = pens[num_colors - 1]; /* use brightest color */
/* Set shadow pen */
ri->ri_ShadowPen = pens[0]; /* use darkest color */
/* Set back pen */
i = 1; /* use 2nd darkest color */
if (! pens[i]) { /* don't use normal background color */
i++;
}
ri->ri_BackPen = pens[i];
back_color = colors[i]; /* new background color */
} else {
/* Set render pens - highlight pen first */
i = num_colors - 1; /* use brightest color */
if (! pens[i]) { /* don't use normal background color */
i--;
}
ri->ri_HighlightPen = pens[i];
/* Set shadow pen */
i = 0; /* use darkest color */
if (! pens[i]) { /* don't use normal background color */
i++;
}
ri->ri_ShadowPen = pens[i];
/* Set back pen */
ri->ri_BackPen = 0;
}
/* Set text pen 1 - use color with greatest difference to
* back color */
for (i = 0, max_diff = 0; i < num_colors; i++) {
SHORT diff;
if ((diff = calc_color_difference(colors[i],
back_color)) > max_diff) {
max_diff = diff;
ri->ri_TextPen1 = pens[i];
}
}
/* Set text pen 2 - use color with greatest difference to
* back color and other color than highlight or shadow pen */
for (i = 0, max_diff = 0; i < num_colors; i++) {
SHORT diff;
if ((diff = calc_color_difference(colors[i],
back_color)) > max_diff) {
SHORT text1_pen = ri->ri_TextPen1, text2_pen = pens[i];
/* Don't use text 1 pen again */
if (text2_pen != text1_pen) {
/* Use special algorithm for 1 and 2 bitplanes */
if (num_colors < 5) {
/* Try to get the pen not used for highlight and
* shadow color if this isn't already used for
* text 1 color */
if ((text1_pen != ri->ri_HighlightPen &&
text1_pen != ri->ri_ShadowPen) ||
(text2_pen != ri->ri_HighlightPen &&
text2_pen != ri->ri_ShadowPen)) {
max_diff = diff;
ri->ri_TextPen2 = pens[i];
}
} else {
/* Try to get the best one from pens not used for
* highlight and shadow color */
if (text2_pen != ri->ri_HighlightPen &&
text2_pen != ri->ri_ShadowPen) {
max_diff = diff;
ri->ri_TextPen2 = pens[i];
}
}
}
}
}
}
/* Get font and attributes for rendering texts */
if (!(flags & RENDER_INFO_FLAG_AVAIL_FONTS) ||
create_avail_fonts(ri) == TRUE) {
struct TextFont *tf;
/* First try to open screen font - if any */
Forbid();
if (!screen->Font) {
tf = NULL;
} else {
tf = open_font(ri, screen->Font);
}
Permit();
if (tf) {
struct TextAttr *ta = &ri->ri_TextAttr;
/* Build text attribute structure from screen font */
ta->ta_Name = (STRPTR)tf->tf_Message.mn_Node.ln_Name;
ta->ta_YSize = tf->tf_YSize;
ta->ta_Style = tf->tf_Style;
ta->ta_Flags = tf->tf_Flags;
} else {
/* Fall back to TOPAZ80 */
if (tf = open_font(ri, &topaz80_attr)) {
CopyMem((BYTE *)&topaz80_attr, (BYTE *)&ri->ri_TextAttr,
(LONG)sizeof(struct TextAttr));
}
}
if (ri->ri_TextFont = tf) {
init_render_info_images(ri);
return(ri);
}
free_avail_fonts(ri);
}
}
}
FreeMem(ri, (LONG)sizeof(struct RenderInfo));
}
return(NULL);
}
/* Free render info */
VOID
free_render_info(struct RenderInfo *ri)
{
if (ri && ri->ri_ID == ISUP_ID) {
if (ri->ri_TextFont) {
CloseFont(ri->ri_TextFont);
}
free_avail_fonts(ri);
FreeMem(ri->ri_ImageData, ri->ri_ImageDataSize);
FreeMem(ri, (LONG)sizeof(struct RenderInfo));
}
}
/* Calc color level with specified scaling values */
STATIC SHORT
calc_color_level(SHORT color)
{
return(calc_color_difference(color, 0));
}
/* Calc color difference with specified scaling values */
SHORT /* non static - needed by menus.c too */
calc_color_difference(SHORT color1, SHORT color2)
{
USHORT temp, diff;
temp = (color1 & 0x00f) - (color2 & 0x00f);
diff = temp * temp * BLUE_SCALE;
temp = ((color1 >> 4) & 0x00f) - ((color2 >> 4) & 0x00f);
diff += temp * temp * GREEN_SCALE;
temp = ((color1 >> 8) & 0x00f) - ((color2 >> 8) & 0x00f);
diff += temp * temp * RED_SCALE;
return(diff);
}
/* Init render info images */
STATIC VOID
init_render_info_images(struct RenderInfo *ri)
{
struct Image *image_src = &images[0], *image_dest = &ri->ri_Images[0];
USHORT i, *data = ri->ri_ImageData;
CopyMem((BYTE *)image_src, (BYTE *)image_dest,
(LONG)(MAX_RENDER_IMAGES * sizeof(struct Image)));
for (i = 0; i < MAX_RENDER_IMAGES; i++, image_src++, image_dest++) {
/* Set image depth first - needed by pixel functions */
image_dest->Depth = ri->ri_ScreenDepth;
/* Init image data if any */
if (image_src->ImageData) {
USHORT y, width = image_src->Width, height = image_src->Height,
depth = image_dest->Depth; /* DEST image depth !!! */
/* Set data buffer ptr */
image_dest->ImageData = data;
image_dest->PlanePick = (1 << depth) - 1;
data += (width / 16 + (width & 15 ? 1 : 0)) * height * depth;
/* Convert image data to current colors */
for (y = 0; y < height; y++) {
USHORT x;
for (x = 0; x < width; x++) {
UBYTE color;
switch(get_image_pixel_color(image_src, x, y)) {
case 0 : /* back pen */
color = ri->ri_BackPen;
break;
case 1 : /* highlight pen */
color = ri->ri_HighlightPen;
break;
case 2 : /* shadow pen */
color = ri->ri_ShadowPen;
break;
default : /* special pen */
color = ri->ri_TextPen2;
break;
}
set_image_pixel_color(image_dest, x, y, color);
}
}
} else {
UBYTE color;
/* No image data -> monochrome rectangle */
switch(image_src->PlaneOnOff) {
case 0 : /* back pen */
color = ri->ri_BackPen;
break;
case 1 : /* highlight pen */
color = ri->ri_HighlightPen;
break;
case 2 : /* shadow pen */
color = ri->ri_ShadowPen;
break;
default : /* special pen */
color = ri->ri_TextPen2;
break;
}
image_dest->PlaneOnOff = color;
}
}
}
/* Get color of image pixel */
STATIC UBYTE
get_image_pixel_color(struct Image *image, USHORT x, USHORT y)
{
USHORT modulo = image->Width / 16 + (image->Width & 15 ? 1 : 0),
*data = image->ImageData + y * modulo + x / 16,
data_offset = image->Height * modulo,
bit_mask = 0x8000 >> (x & 15);
UBYTE i, depth = image->Depth, color_mask = 1, color = 0;
for (i = 0; i < depth; i++, data += data_offset, color_mask <<= 1) {
if (*data & bit_mask) {
color |= color_mask;
}
}
return(color);
}
/* Set color of image pixel */
STATIC VOID
set_image_pixel_color(struct Image *image, USHORT x, USHORT y, UBYTE color)
{
USHORT modulo = image->Width / 16 + (image->Width & 15 ? 1 : 0),
*data = image->ImageData + y * modulo + x / 16,
data_offset = image->Height * modulo,
bit_mask = 0x8000 >> (x & 15);
UBYTE i, depth = image->Depth;
for (i = 0; i < depth; i++, data += data_offset, color >>= 1) {
if (color & 1) {
*data |= bit_mask;
}
}
}
/* Open window */
struct Window *
open_window(struct RenderInfo *ri, struct NewWindow *org_nw, USHORT flags)
{
struct Window *win = NULL;
if (ri && ri->ri_ID == ISUP_ID && org_nw) {
struct NewWindow new_nw = *org_nw, *nw = &new_nw;
SHORT left_edge = nw->LeftEdge, top_edge = nw->TopEdge;
USHORT width = nw->Width, height = nw->Height,
max_width = ri->ri_ScreenWidth, max_height = ri->ri_ScreenHeight;
/* Scale new window dimension */
if (width > max_width) {
width = max_width;
left_edge = 0;
} else {
if ((left_edge + width) > max_width) {
left_edge = max_width - width;
}
}
if (height > max_height) {
height = max_height;
top_edge = 0;
} else {
if ((top_edge + height) > max_height) {
top_edge = max_height - height;
}
}
/* Change new window struct */
if (flags & OPEN_WINDOW_FLAG_RENDER_PENS) {
/* Set colors */
if (ri->ri_Flags & RENDER_INFO_FLAG_BACK_FILL) {
nw->DetailPen = ri->ri_TextPen1;
nw->BlockPen = ri->ri_BackPen;
} else {
nw->DetailPen = ri->ri_BackPen;
nw->BlockPen = ri->ri_TextPen1;
}
}
if (!(flags & OPEN_WINDOW_FLAG_NO_INNER_WINDOW) &&
(ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW)) {
USHORT hoffset = ri->ri_WindowBorderLeft,
voffset = ri->ri_WindowBorderTop;
/* Change width and left edge for inner window dimension */
if ((width += hoffset + ri->ri_WindowBorderRight) > max_width) {
width = max_width;
left_edge = 0;
} else {
if (left_edge > hoffset) {
left_edge -= hoffset;
if ((left_edge + width) > max_width) {
left_edge = max_width - width;
}
} else {
left_edge = 0;
}
}
/* Change height and top edge for inner window dimension */
if ((height += voffset + ri->ri_WindowBorderBottom) > max_height) {
height = max_height;
top_edge = 0;
} else {
if (top_edge > voffset) {
top_edge -= voffset;
if ((top_edge + height) > max_height) {
top_edge = max_height - height;
}
} else {
top_edge = 0;
}
}
}
/* Center window AFTER calculation of inner window dimension */
if (flags & OPEN_WINDOW_FLAG_CENTER_SCREEN) {
/* Center window on screen */
left_edge = (max_width - width) / 2;
top_edge = (max_height - height) / 2;
} else {
if (flags & OPEN_WINDOW_FLAG_CENTER_MOUSE) {
/* Center window over current position of mouse pointer */
left_edge = ri->ri_Screen->MouseX - width / 2;
top_edge = ri->ri_Screen->MouseY - height / 2;
/* Scale window position according to screen dimension */
if (left_edge < 0) {
left_edge = 0;
} else {
if (left_edge > (max_width - width)) {
left_edge = max_width - width;
}
}
if (top_edge < 0) {
top_edge = 0;
} else {
if (top_edge > (max_height - height)) {
top_edge = max_height - height;
}
}
}
}
/* Insert position + dimension of window and try to open it */
nw->LeftEdge = left_edge;
nw->TopEdge = top_edge;
nw->Width = width;
nw->Height = height;
if (win = OpenWindow(nw)) {
/* Finally fill window background */
if (ri->ri_Flags & RENDER_INFO_FLAG_BACK_FILL) {
clear_window(ri, win, 0, 0, width, height, 0);
}
}
}
return(win);
}
/* Clear given rectangle of window with data from render info */
VOID
clear_window(struct RenderInfo *ri, struct Window *win, USHORT left_edge,
USHORT top_edge, USHORT width, USHORT height, USHORT flags)
{
if (ri && ri->ri_ID == ISUP_ID && win) {
USHORT inner_left, inner_top, inner_width, inner_height,
ri_flags = ri->ri_Flags;
/* Calc inner window dimension */
if ((ri_flags & RENDER_INFO_FLAG_INNER_WINDOW) ||
(ri_flags & RENDER_INFO_FLAG_BACK_FILL)) {
inner_left = ri->ri_WindowBorderLeft;
inner_top = ri->ri_WindowBorderTop;
inner_width = win->Width - inner_left - ri->ri_WindowBorderRight;
inner_height = win->Height - inner_top - ri->ri_WindowBorderBottom;
} else {
inner_left = 0;
inner_top = 0;
inner_width = win->Width;
inner_height = win->Height;
}
/* Check if given rectangle fits into inner window */
if ((SHORT)left_edge >= 0 && (SHORT)top_edge >= 0 && width &&
height && left_edge < (inner_left + inner_width) &&
top_edge < (inner_top + inner_height)) {
struct RastPort *rp = win->RPort;
/* Add offsets for inner window to given upper left position */
if (!(flags & CLEAR_WINDOW_FLAG_ABSOLUTE_POS)) {
left_edge += inner_left;
top_edge += inner_top;
/* Scale upper left position of given rectangle if neccessary */
if (left_edge < inner_left) {
left_edge = inner_left;
}
if (top_edge < inner_top) {
top_edge = inner_top;
}
}
/* Scale dimension of given rectangle if neccessary */
if ((SHORT)width <= 0 || (left_edge + width) > (inner_left +
inner_width)) {
width = inner_left + inner_width - left_edge;
}
if ((SHORT)height <= 0 || (top_edge + height) > (inner_top +
inner_height)) {
height = inner_top + inner_height - top_edge;
}
/* Set draw mode, colors and fill pattern for using raster */
if (flags & CLEAR_WINDOW_FLAG_USE_RASTER) {
STATIC USHORT raster_pattern[] = { 0xaaaa, 0x5555 };
SetDrMd(rp, (LONG)JAM2);
SetAPen(rp, (LONG)ri->ri_HighlightPen);
SetBPen(rp, (LONG)ri->ri_BackPen);
SetAfPt(rp, &raster_pattern[0], 1L); /* macro !!! */
} else {
/* Set draw mode */
if (!(flags & CLEAR_WINDOW_FLAG_CUSTOM_DRAW_MODE)) {
SetDrMd(rp, (LONG)JAM1);
}
/* Set fill colors */
if (!(flags & CLEAR_WINDOW_FLAG_CUSTOM_COLOR)) {
USHORT apen;
/* Check if special color needed */
if (flags & CLEAR_WINDOW_FLAG_TEXT1_COLOR) {
apen = ri->ri_TextPen1;
} else {
if (flags & CLEAR_WINDOW_FLAG_TEXT2_COLOR) {
apen = ri->ri_TextPen2;
} else {
/* Use background color */
if ((ri_flags & RENDER_INFO_FLAG_BACK_FILL) &&
!(flags & CLEAR_WINDOW_FLAG_NORMAL_COLOR)) {
apen = ri->ri_BackPen;
} else {
apen = 0;
}
}
}
SetAPen(rp, (LONG)apen);
}
}
/* And do clearing window background */
RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge +
width - 1), (LONG)(top_edge + height - 1));
/* Clear fill pattern */
if (flags & CLEAR_WINDOW_FLAG_USE_RASTER) {
SetAfPt(rp, NULL, 1L); /* macro !!! */
}
}
}
}
/* Close window safely, even if shared user port */
VOID
close_window(struct Window *win, BOOL more_windows)
{
if (win) {
/* Check if any IDCMP flag used */
if (win->UserPort) {
struct IntuiMessage *msg, *succ;
/* Reply all messages for given window */
Forbid();
msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
while (succ = (struct IntuiMessage *)
msg->ExecMessage.mn_Node.ln_Succ) {
if (more_windows == FALSE || msg->IDCMPWindow == win) {
Remove((struct Node *)msg);
ReplyMsg((struct Message *)msg);
}
msg = succ;
}
/* Don't close shared user port */
if (more_windows == TRUE) {
win->UserPort = NULL;
ModifyIDCMP(win, 0L);
}
Permit();
}
CloseWindow(win);
}
}
/* Create list of available fonts - called by create_render_info() */
STATIC BOOL
create_avail_fonts(struct RenderInfo *ri)
{
struct AvailFontsHeader *afh;
LONG size = DEFAULT_AVAIL_FONTS_BUFFER_SIZE;
BOOL success = FALSE;
/* Allocate buffer and fill it with data from available fonts */
if (afh = AllocMem(size, (LONG)MEMF_PUBLIC)) {
LONG new_size;
if (new_size = AvailFonts((BYTE *)afh, size,
(LONG)AFF_MEMORY | AFF_DISK)) {
/* Allocate larger buffer and try again */
FreeMem(afh, size);
size += new_size;
if (afh = AllocMem(size, (LONG)MEMF_PUBLIC)) {
AvailFonts((BYTE *)afh, size, (LONG)AFF_MEMORY | AFF_DISK);
}
}
/* Save font header in render info data structure */
ri->ri_AvailFontsHeader = afh;
ri->ri_AvailFontsHeaderSize = size;
success = TRUE;
}
return(success);
}
/* Free list of available fonts - called by free_render_info() */
STATIC VOID
free_avail_fonts(struct RenderInfo *ri)
{
if (ri->ri_AvailFontsHeader && ri->ri_AvailFontsHeaderSize) {
FreeMem(ri->ri_AvailFontsHeader, ri->ri_AvailFontsHeaderSize);
}
}
/* Return ptr to list of available fonts */
struct AvailFontsHeader *
avail_fonts(struct RenderInfo *ri)
{
struct AvailFontsHeader *afh = NULL;
if (ri && ri->ri_ID == ISUP_ID &&
(ri->ri_Flags & RENDER_INFO_FLAG_AVAIL_FONTS)) {
afh = ri->ri_AvailFontsHeader;
}
return(afh);
}
/* Check if given font is available and return its correct data */
struct TextAttr *
ask_font(struct RenderInfo *ri, struct TextAttr *ta)
{
struct TextAttr *best_ta = NULL;
if (ri && ri->ri_ID == ISUP_ID && ta) {
if (!(ri->ri_Flags & RENDER_INFO_FLAG_AVAIL_FONTS)) {
best_ta = ta;
} else {
struct AvailFontsHeader *afh = ri->ri_AvailFontsHeader;
USHORT num = afh->afh_NumEntries;
if (num) {
struct AvailFonts *af = (struct AvailFonts *)(afh + 1);
USHORT search_ysize = ta->ta_YSize, best_ysize = 0;
do {
struct TextAttr *avail_ta = &af++->af_Attr;
int stricmp(const char *_s1, const char *_s2); /* manually prototyping non ANSI function */
if (!stricmp((BYTE *)avail_ta->ta_Name, (BYTE *)ta->ta_Name)) {
USHORT avail_ysize = avail_ta->ta_YSize;
if (avail_ysize == search_ysize) {
best_ta = avail_ta;
break;
} else {
if (avail_ysize < search_ysize) {
if (avail_ysize > best_ysize) {
best_ysize = avail_ysize;
best_ta = avail_ta;
}
} else {
if (!best_ysize || avail_ysize < best_ysize) {
best_ysize = avail_ysize;
best_ta = avail_ta;
}
}
}
}
} while (--num);
}
}
}
return(best_ta);
}
/* Open best available text font */
struct TextFont *
open_font(struct RenderInfo *ri, struct TextAttr *ta)
{
struct TextFont *tf = NULL;
if (ri && ri->ri_ID == ISUP_ID && ta) {
if (ta = ask_font(ri, ta)) {
if (!(tf = OpenFont(ta)) || tf->tf_YSize != ta->ta_YSize) {
if (tf) {
CloseFont(tf);
}
tf = OpenDiskFont(ta);
}
}
}
return(tf);
}